package com.bl.student.service.biz.main.impl;

import com.bl.student.common.ApiResponseCode;
import com.bl.student.common.CommonServiceException;
import com.bl.student.common.enums.PointType;
import com.bl.student.common.enums.UserStatus;
import com.bl.student.common.utils.ASE;
import com.bl.student.common.utils.Generator;
import com.bl.student.common.utils.ListUtils;
import com.bl.student.common.utils.UUIDUtils;
import com.bl.student.dao.model.PointEntity;
import com.bl.student.dao.model.TeacherEntity;
import com.bl.student.dao.model.UserEntity;
import com.bl.student.dao.redis.MessageDao;
import com.bl.student.dao.redis.UserInfoDao;
import com.bl.student.dao.redis.model.UserInfo;
import com.bl.student.dao.repository.PointRepository;
import com.bl.student.dao.repository.TeacherRepository;
import com.bl.student.dao.repository.UserRepository;
import com.bl.student.dao.repository.UserTagRepository;
import com.bl.student.service.biz.hx.HxAuthService;
import com.bl.student.service.biz.main.MainService;
import com.bl.student.service.biz.point.PointService;
import com.bl.student.service.biz.teacher.TeacherMainService;
import com.bl.student.service.biz.teacher.TeacherService;
import com.bl.student.service.biz.user.UserService;
import com.bl.student.service.biz.vip.VipService;
import com.bl.student.service.vo.main.*;
import com.bl.student.service.vo.teacher.TeacherRegisterVo;
import com.bl.student.tp.hx.user.*;
import com.bl.student.tp.wechat.auth.WechatAccessTokenMiniRequest;
import com.bl.student.tp.wechat.auth.WechatAccessTokenResponse;
import com.bl.student.tp.wechat.auth.WechatAuthApi;
import com.gexin.fastjson.JSONObject;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * Created by yujingyi on 2018/1/18.
 */
@Log4j2
@Service
public class MainServiceImpl implements MainService {

    private final String REGISTER_DUPLICATED_PHONE = "该手机号码已被注册";
    private final String REGISTER_DUPLICATED_ACCOUNT = "该帐号已被注册";

    @Autowired
    MessageDao messageDao;

    @Autowired
    UserService userService;

    @Autowired
    UserRepository userRepository;

    @Autowired
    HxUserApi hxUserApi;

    @Autowired
    UserInfoDao userInfoDao;

    @Autowired
    HxAuthService hxAuthService;

    @Autowired
    VipService vipService;

    @Autowired
    WechatAuthApi wechatAuthApi;

    @Autowired
    MainService mainService;

    @Autowired
    PointService pointService;

    @Autowired
    TeacherMainService teacherMainService;

    @Autowired
    UserTagRepository tagRepository;

    @Autowired
    PointRepository pointRepository;

    @Autowired
    TeacherRepository teacherRepository;

    private boolean verifyCaptcha(String mobile, String captcha) {
        String code = messageDao.getAuthCode(mobile);
        if (code == null || !code.equals(captcha)) {
            return false;
        }
        return true;
    }

    @Override
    @Transactional
    public LoginResponseVo register(RegisterVo registerVo, String openId) {

        if (userService.getUserByMobile(registerVo.getMobile()) != null) {
            throw new CommonServiceException(ApiResponseCode.DATA_EXISTED.getCode(), REGISTER_DUPLICATED_PHONE);
        }

        if (!verifyCaptcha(registerVo.getMobile(), registerVo.getCaptcha())) {
            throw new CommonServiceException(ApiResponseCode.CAPTCHA_WRONG.getCode(), ApiResponseCode.CAPTCHA_WRONG.getMsg());
        }


        UserEntity userEntity = userService.getUserByOpenId(openId);
        if (userEntity == null) {
            throw new CommonServiceException(ApiResponseCode.DATA_EXISTED.getCode(), "未授权,无法注册");
        }
        if (!userEntity.getMobile().isEmpty()) {
            throw new CommonServiceException(ApiResponseCode.DATA_EXISTED.getCode(), "该微信已经绑定过手机，请使用手机登录");
        }
        //增加注册积分
        PointEntity pointEntity0 = pointRepository.findByType("REGISTER");
        int point0 = pointEntity0.getValue();
        // 增加积分
        pointService.addPoint(userEntity.getId(), point0);
        // 增加记录
        pointService.addUserPoint(userEntity.getId(), PointType.REGISTER, point0, "0");

        // handle invite code
        String inviteCode = registerVo.getInviteCode();
        if (!Strings.isNullOrEmpty(inviteCode)) {
            UserEntity inviter = userService.getUserByInviteCode(inviteCode);
            List<TeacherEntity> teacherEntityList = teacherRepository.findByOpenId(inviter.getOpenId());
            if (inviter != null) {
                TeacherEntity teacherEntity = ListUtils.getFirst(teacherEntityList);
                userService.addUserInvite(inviter.getId(), userEntity.getId());
                PointEntity pointEntity = pointRepository.findByType("INVITE");
                int point = pointEntity.getValue();
                // 增加积分
                pointService.addPoint(inviter.getId(), point);
                // 增加记录
                pointService.addUserPoint(inviter.getId(), PointType.INVITE, point, "0");

                // 甲方增加积分
                pointService.addPointPartyA(teacherEntity.getId(), point);
                // 甲方增加记录
                pointService.addTeacherPoint(teacherEntity.getId(), PointType.INVITE, point, "0");
            }

//            if (inviter == null) {
//                throw new CommonServiceException(ApiResponseCode.DATA_EXISTED.getCode(), "邀请码填写错误");
//            }
        }

        // register hx
        HxUserRegisterRequest hxUserRegisterRequest = HxUserRegisterRequest.builder()
                .nickname(userEntity.getNickname())
                .password(registerVo.getPassword())
                .username(registerVo.getMobile())
                .build();

        Optional<HxUserRegisterResponse> hxUserRegisterResponseOptional = hxUserApi.register(hxUserRegisterRequest);

        // request failed
        if (!hxUserRegisterResponseOptional.isPresent()) {
            throw new CommonServiceException(ApiResponseCode.HX_REQUEST_FAILED.getCode(), ApiResponseCode.HX_REQUEST_FAILED.getMsg());
        }

        HxUserRegisterResponse hxUserRegisterResponse = hxUserRegisterResponseOptional.get();
        String hxId = hxUserRegisterResponse.getEntities().get(0).getUuid();
        String hxName =  hxUserRegisterResponse.getEntities().get(0).getUsername();


        userEntity.setMobile(registerVo.getMobile());
        userEntity.setPassword(registerVo.getPassword());
        userEntity.setInviteCode(Generator.generateInviteCode());
        userEntity.setCreateTime(new Date());
        userEntity.setAuth("0");
        userEntity.setHxId(hxId);
        userEntity.setHxName(hxName);
        userRepository.save(userEntity);


        TeacherRegisterVo teacherRegisterVo = new TeacherRegisterVo();
        teacherRegisterVo.setInviteCode(registerVo.getInviteCode());
        teacherRegisterVo.setMobile(registerVo.getMobile());
        teacherRegisterVo.setPassword(registerVo.getPassword());
        teacherRegisterVo.setHxName(hxName);
        teacherRegisterVo.setSelfInviteCode(userEntity.getInviteCode());
        teacherRegisterVo.setHxId(hxId);

        // 甲方注册
        teacherMainService.register(teacherRegisterVo, openId, hxId);


        String token = Generator.generateToken(userEntity.getId(), userEntity.getMobile(), userEntity.getPassword());
        LoginResponseVo loginResponseVo;
        loginResponseVo = LoginResponseVo.builder()
                .mobile(userEntity.getMobile())
                .name(userEntity.getNickname())
                .token(token)
                .hxId(hxId)
                .hxName(hxName)
                .hxPwd(userEntity.getPassword())
                .unionId(userEntity.getUnionId())
                .avatar(userEntity.getAvatar())
                .openId(userEntity.getOpenId())
                .id(userEntity.getId())
                .build();

        return loginResponseVo;
    }

    @Override
    public LoginResponseVo appLogin(LoginVo loginVo, String unionId) {
        UserEntity userEntity = fetchAvailableUser(loginVo.getMobile(), loginVo.getPassword());

        String token = Generator.generateToken(userEntity.getId(), userEntity.getMobile(), userEntity.getPassword());

        UserInfo userInfo = new UserInfo();
        userInfo.setId(userEntity.getId());
        userInfo.setMobile(userEntity.getMobile());
        userInfo.setAccount(userEntity.getAccount());
        userInfo.setToken(token);
        userInfo.setType("PARTYB");
        userInfo.setHxId(userEntity.getHxId());

        userInfoDao.setUserInfo(userInfo);

        LoginResponseVo loginResponseVo;
        loginResponseVo = LoginResponseVo.builder()
                .mobile(userEntity.getMobile())
                .name(userEntity.getNickname())
                .token(token)
                .hxName(userEntity.getHxName())
                .type("PARTYB")
                .hxId(userEntity.getHxId())
                .unionId(userEntity.getUnionId())
                .avatar(userEntity.getAvatar())
                .openId(userEntity.getOpenId())
                .id(userEntity.getId())
                .build();

        return loginResponseVo;
    }

    private UserEntity fetchAvailableUser(String mobile, String password) {
        UserEntity userEntity = userService.getUserByMobile(mobile);

        if (userEntity == null) {
            throw new CommonServiceException(ApiResponseCode.USER_NOT_EXIST.getCode(), ApiResponseCode.USER_NOT_EXIST.getMsg());
        }

        if (!userEntity.getPassword().equals(password)) {
            throw new CommonServiceException(ApiResponseCode.PASSWORD_WRONG.getCode(), ApiResponseCode.PASSWORD_WRONG.getMsg());
        }

        if (userEntity.getStatus() == UserStatus.LOCKED) {
            throw new CommonServiceException(ApiResponseCode.USER_LOCKED.getCode(), ApiResponseCode.USER_LOCKED.getMsg());
        }
        return userEntity;
    }

    private void handleInvitedCode() {

    }

    @Override
    public void reset(ResetVo resetVo) {
        UserEntity userEntity = userService.getUserByMobile(resetVo.getMobile());
        if (userEntity == null) {
            throw new CommonServiceException(ApiResponseCode.USER_NOT_EXIST.getCode(), ApiResponseCode.USER_NOT_EXIST.getMsg());
        }

        if (!verifyCaptcha(resetVo.getMobile(), resetVo.getCaptcha())) {
            throw new CommonServiceException(ApiResponseCode.CAPTCHA_WRONG.getCode(), ApiResponseCode.CAPTCHA_WRONG.getMsg());
        }

        userEntity.setPassword(resetVo.getPassword());

//        // update in hx
//        String accessToken = hxAuthService.getAndSetAccessToken();
//        HxUserPasswordRequest hxUserPasswordRequest = HxUserPasswordRequest.builder()
//                .newpassword(resetVo.getPassword())
//                .build();
//        Optional<HxUserPasswordResponse> hxUserPasswordResponseOptional = hxUserApi
//                .resetPassword(userEntity.getMobile(), accessToken, hxUserPasswordRequest);
//        if (!hxUserPasswordResponseOptional.isPresent()) {
//            throw new CommonServiceException(ApiResponseCode.HX_REQUEST_FAILED.getCode(), ApiResponseCode.HX_REQUEST_FAILED.getMsg());
//        }
        userRepository.save(userEntity);

        List<TeacherEntity> teacherEntities = teacherRepository.findByMobile(resetVo.getMobile());
        TeacherEntity teacherEntity = ListUtils.getFirst(teacherEntities);
        teacherEntity.setPassword(resetVo.getPassword());
        teacherRepository.save(teacherEntity);

    }

    @Override
    public void register(RegisterVo registerVo) {
        // register hx
        HxUserRegisterRequest hxUserRegisterRequest = HxUserRegisterRequest.builder()
                .nickname(registerVo.getMobile())
                .password(registerVo.getPassword())
                .username(registerVo.getMobile())
                .build();

        Optional<HxUserRegisterResponse> hxUserRegisterResponseOptional = hxUserApi.register(hxUserRegisterRequest);

        // request failed
        if (!hxUserRegisterResponseOptional.isPresent()) {
            throw new CommonServiceException(ApiResponseCode.HX_REQUEST_FAILED.getCode(), ApiResponseCode.HX_REQUEST_FAILED.getMsg());
        }

        HxUserRegisterResponse hxUserRegisterResponse = hxUserRegisterResponseOptional.get();
        String hxId = hxUserRegisterResponse.getEntities().get(0).getUuid();
    }

    @Override
    public void logout(UserInfo userInfo) {
        userInfoDao.delUserInfo(userInfo.getMobile());
    }

    @Override
    public LoginResponseVo miniWechatLogin(String code, String encryptedData, String iv) {
        LoginResponseVo loginResponseVo = LoginResponseVo.builder().build();
        Optional<WechatAccessTokenResponse> optional;
        WechatAccessTokenMiniRequest wechatAccessTokenMiniRequest = new WechatAccessTokenMiniRequest();
        wechatAccessTokenMiniRequest.setJs_code(code);
        wechatAccessTokenMiniRequest.setAppid("wx0fba90b1a1f3f0a1");
        wechatAccessTokenMiniRequest.setSecret("2de7269905cac3af88558e94539b8c5c");
        optional = wechatAuthApi.getAccessTokenMini(wechatAccessTokenMiniRequest);
        log.info("optional ===" + optional.toString());
        if (!optional.isPresent()) {
            throw new CommonServiceException(ApiResponseCode.WECHAT_AUTH_FAILED.getCode(),
                    ApiResponseCode.WECHAT_AUTH_FAILED.getMsg());
        }

        WechatAccessTokenResponse wechatAccessTokenResponse = optional.get();

        String result = null;
        try {
            result = ASE.decrypt(encryptedData, wechatAccessTokenResponse.getSession_key(), iv, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (null != result && result.length() > 0) {

            JSONObject userInfoJSON = JSONObject.parseObject(result);
            loginResponseVo.setName(userInfoJSON.get("nickName").toString());
            loginResponseVo.setAvatar(userInfoJSON.get("avatarUrl").toString());
            if (userInfoJSON.get("unionId") != null) {
                loginResponseVo.setUnionId(userInfoJSON.get("unionId").toString());
            }
            loginResponseVo.setOpenId(userInfoJSON.get("openId").toString());

            UserEntity user = userService.getUserByOpenId(loginResponseVo.getOpenId());
            log.info("saveInviteIntoDB user pre===>" + user);
            if (user == null) {
                // user not existed, create user
                mainService.createWechatUser(userInfoJSON.get("nickName").toString(), 1, loginResponseVo.getAvatar(), loginResponseVo.getOpenId(), loginResponseVo.getUnionId());
                teacherMainService.createWechatUser(userInfoJSON.get("nickName").toString(), 1, loginResponseVo.getAvatar(), loginResponseVo.getOpenId(), loginResponseVo.getUnionId());
            }

        }
        return loginResponseVo;
    }

    @Override
    public UserEntity createWechatUser(String nickname, int sex, String avatar, String openId, String unionId) {
        UserEntity user = new UserEntity();
        String userId = UUIDUtils.getUUID();
        user.setId(userId);
        user.setOpenId(openId);
        user.setUnionId(unionId);
        user.setMobile("");
        user.setStatus(UserStatus.NORMAL);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setAvatar(avatar);
        user.setNickname(openId.substring(6));
        userRepository.save(user);

        return user;
    }

}
